#ifndef THREADPOOL_HPP
#define THREADPOOL_HPP

#include "TaskQueue.hpp"
#include <atomic>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <queue>
#include <signal.h>
#include <string.h>
#include <thread>
#include <vector>

#define CHECK_INTERVAL 3 // 检查时间间隔
#define NUMBER 2         // 一次加入的线程数

using namespace std;

// 线程池结构体
template <class T>
class ThreadPool
{
public:
    ThreadPool();
    explicit ThreadPool(unsigned int min, unsigned int max);
    ~ThreadPool();

    void addTask(const Task<T> &task);
    unsigned int getBusyNum();  // 忙的线程个数
    unsigned int getAliveNum(); // 活的线程个数
private:
    void threadExit();               // 线程退出
    static void *worker(void *arg);  // 静态函数，工作线程调用
    static void *manager(void *arg); // 静态函数，管理者线程调用

    // 任务队列
    TaskQueue<T> *taskQueue;

    thread *managerThread; // 管理者线程

    vector<thread> workGroup; // 工作线程组

    unsigned int minNum; // 最小线程数
    unsigned int maxNum; // 最大线程数

    atomic<unsigned int> busyNum; // 忙的线程的个数
    atomic<unsigned int> liveNum; // 存活的线程的个数
    atomic<unsigned int> exitNum; // 要销毁的线程个数

    mutex mutexPool;             // 锁整个线程池
    condition_variable notEmpty; // 任务队列是否为空，空则进行需要等任务

    bool isShutdown; // 线程池销毁 true
};

template <class T>
ThreadPool<T>::ThreadPool() {}

template <class T>
ThreadPool<T>::ThreadPool(unsigned int min, unsigned int max)
{
    taskQueue = new TaskQueue<T>;
    if (nullptr == taskQueue)
    {
        cout << "创建任务队列失败..." << endl;
        return;
    }
    workGroup.reserve(max); // 数组分配最大容量

    minNum  = min;
    maxNum  = max;
    busyNum = 0;
    liveNum = min;
    exitNum = 0;

    isShutdown = false;

    // 管理者线程
    managerThread = new thread(manager, this);

    if (nullptr == managerThread)
    {
        cout << "创建管理者线程失败..." << endl;
        return;
    }

    // 创建min个工作线程
    for (unsigned int i = 0; i < min; ++i)
        workGroup.push_back(thread(worker, this));
}

template <class T>
ThreadPool<T>::~ThreadPool()
{
    isShutdown = true;

    // 唤醒所有等待任务的工作线程，isShutdown设为true后，线程会主动关闭
    if (liveNum > 0)
    {
        notEmpty.notify_all();
        cout << "唤醒所有阻塞的工作线程..." << endl;
    }

    if (taskQueue)
        delete taskQueue;

    if (managerThread != nullptr)
    {
        // 设置managerThread为守护线程时
        // c++运行库可以保证managerThread相关资源回收
        if (managerThread->joinable())
        {
            managerThread->join();
        }
        cout << "销毁管理者线程..." << endl;
        delete managerThread;
    }
    if (!workGroup.empty())
    {
        threadExit();
    }

    cout << "任务队列大小：" << taskQueue->taskNumber() << endl;
    cout << "线程池大小：" << workGroup.size() << endl;
    cout << "忙的线程个数：" << busyNum << endl;
    cout << "活的线程个数：" << liveNum << endl;
    cout << "线程池销毁成功..." << endl;
}

// 关键函数：工作线程的执行函数：worker，静态函数，需要传入this指针访问非静态成员
// 流程：线程池中的工作线程，如果没有任务，循环等待任务到来（等待notEmpty条件变量的通知）
// 如果有任务，从任务队列中取出一个任务，执行该任务
template <class T>
void *ThreadPool<T>::worker(void *arg)
{
    cout << this_thread::get_id() << "号工作线程启动..." << endl;

    ThreadPool *pool = static_cast<ThreadPool *>(arg); // 类型转换
    while (true)
    {
        unique_lock<mutex> poolLock(pool->mutexPool);

        // 没关闭且任务队列为空，等待任务来临
        while (0 == pool->taskQueue->taskNumber() && !pool->isShutdown)
        {
            cout << this_thread::get_id() << "号工作线程等待任务... !isShutdown" << endl;
            pool->notEmpty.wait(poolLock); // 阻塞等待任务（唤醒后自动上锁）

            // 判断是否销毁线程，exitNum由manager线程设置
            if (pool->exitNum > 0 && pool->liveNum > pool->minNum)
            {
                --pool->exitNum;
                --pool->liveNum;

                cout << this_thread::get_id() << "号工作线程退出..." << endl;
                poolLock.unlock();
                return nullptr; // 退出线程
            }
        }

        // 线程池关闭
        if (pool->isShutdown)
        {
            cout << this_thread::get_id() << "号工作线程退出... isShutdown" << endl;
            poolLock.unlock();
            return nullptr; // 退出线程
        }

        // 有任务，取出一个任务
        Task<T> task = pool->taskQueue->takeTask();
        poolLock.unlock();

        ++pool->busyNum;
        task.function(task.arg); // 执行函数
        delete task.arg;
        --pool->busyNum;
    }
}

// 线程池中的管理者线程，每隔CHECK_INTERVAL时间检查线程池中的线程数量
// 1.如果【忙的线程数小于存活线程数】，唤醒一个等待任务的线程
// 2.如果任务队列中的【任务数大于存活线程数，且存活线程数小于最大线程数】，创建新线程
// 3.如果【任务数小于存活线程数，且存活线程数大于最小线程数】，销毁线程
template <class T>
void *ThreadPool<T>::manager(void *arg)
{
    cout << this_thread::get_id() << "号管理者线程启动..." << endl;
    ThreadPool *pool = static_cast<ThreadPool *>(arg);

    // 只要线程池没有关闭，就一直检查
    while (!pool->isShutdown)
    {
        this_thread::sleep_for(chrono::seconds(CHECK_INTERVAL)); // 每3秒检查
        unique_lock<mutex> poolLock(pool->mutexPool);            // 上锁

        unsigned int queueSize = pool->taskQueue->taskNumber();

        // 1.如果【忙的线程数小于存活线程数】，唤醒一个等待任务的线程
        unsigned int sleepThreadNum = pool->liveNum - pool->busyNum;
        if (pool->busyNum < queueSize)
        {
            while (sleepThreadNum > 0)
            {
                pool->notEmpty.notify_one();
                --sleepThreadNum;
            }
        }

        // 2.如果任务队列中的【任务数大于存活线程数，且存活线程数小于最大线程数】，创建新线程
        if (queueSize > pool->liveNum && pool->liveNum < pool->maxNum)
        {
            for (unsigned int counter = 0; counter < NUMBER && pool->liveNum < pool->maxNum; ++counter)
            {
                pool->workGroup.push_back(thread(worker, pool));
                --pool->liveNum;
            }
        }

        // 检查时间自适应
        // if ((queueSize * 2 < pool->liveNum || queueSize > 2 * pool->liveNum) && CHECK_INTERVAL > 1)
        // {
        //     checkInterval--;
        // }
        poolLock.unlock();

        // 3.如果【任务数小于存活线程数，且存活线程数大于最小线程数】，销毁线程
        if (pool->busyNum * 2 < pool->liveNum && pool->liveNum > pool->minNum)
        {
            pool->exitNum = NUMBER;
            for (int i = 0; i < NUMBER; ++i)
                pool->notEmpty.notify_one();
        }

        // 有线程结束了工作，调用threadExit函数清理这些线程
        if (pool->workGroup.size() > pool->liveNum)
        {
            pool->threadExit();
        }
    }
    return nullptr;
}

template <class T>
void ThreadPool<T>::threadExit()
{
    // 清空容器里结束的线程
    auto it = workGroup.begin();
    while (it != workGroup.end())
    {
        auto correntTid = (*it).native_handle();       // 获取线程pthread_id
        int kill_rc     = pthread_kill(correntTid, 0); // 发送信号0，探测线程是否存活

        if (kill_rc == ESRCH)
        {
            if ((*it).joinable())
            {
                (*it).join(); // 等待线程结束 清理线程存储
            }
            it      = workGroup.erase(it); // 删除已经结束的线程，it无需++
            liveNum = workGroup.size();
            cout << correntTid << "号工作线程结束...threadExit" << endl;
            // cout << "workGroup.size():" << workGroup.size() << endl;
        }
        else
        {
            ++it;
        }
    }
}

template <class T>
void ThreadPool<T>::addTask(const Task<T> &task)
{
    taskQueue->addTask(task);
}

template <class T>
unsigned int ThreadPool<T>::getBusyNum()
{
    return this->busyNum;
}

template <class T>
unsigned int ThreadPool<T>::getAliveNum()
{
    return this->liveNum;
}

#endif